import type {
  ComputeContext,
  CreateCrudOptionsProps,
  CreateCrudOptionsRet,
  ScopeContext,
} from '@fast-crud/fast-crud';

import type { Ref } from 'vue';

import type { FormRulesExt } from '#/api';

import { isUrl } from '@vben/utils';

import { compute } from '@fast-crud/fast-crud';

import { DefResourceApi, RuleType } from '#/api';
import { IconPicker } from '#/components/form';
import { DictEnum } from '#/enums/commonEnum';
import {
  DataScopeEnum,
  ResourceOpenWithEnum,
  ResourceTypeEnum,
} from '#/enums/system';
import { $t } from '#/locales';
import {
  backendDict,
  STATE_CONSTANT_DICT,
  YES_NO_CONSTANT_DICT,
} from '#/plugins/fast-crud/common';

import Api from '../modules/api.vue';
import Meta from '../modules/meta.vue';

export function createCrudOptions(
  props: CreateCrudOptionsProps,
): CreateCrudOptionsRet {
  return {
    crudOptions: {
      request: {
        addRequest: DefResourceApi.addRequest,
        editRequest: DefResourceApi.editRequest,
      },
      addForm: { mode: 'add' },
      editForm: { mode: 'edit' },
      form: {
        group: {
          type: 'tabs', // collapse, tabs
          accordion: false, // 手风琴模式
          displayDirective: 'show',
          triggerAreas: ['arrow'],
          groups: {
            base: {
              header: '基础信息',
              columns: [
                'resourceType',
                'parentName',
                'code',
                'name',
                'icon',
                'sortValue',
                'state',
                'isGeneral',
              ],
            },
            feature: {
              header: '特性信息',
              columns: [
                'openWith',
                'isHidden',
                'link',
                'path',
                'component',
                'redirect',
                'subGroup',
                'dataScope',
                'isDef',
                'customClass',
                'fieldIsSecret',
                'fieldIsEdit',
                'resourceApiList',
              ],
            },
            extend: { header: '扩展信息', columns: ['metaJson', 'describe'] },
          },
        },
      },
      columns: {
        id: {
          title: 'id',
          form: { show: false },
          type: 'text',
        },
        applicationId: {
          title: $t('devOperation.application.defResource.applicationId'),
          form: { show: false },
          type: 'text',
        },
        parentId: {
          title: 'parentId',
          form: { show: false },
          type: 'text',
        },
        resourceType: {
          title: $t('devOperation.application.defResource.resourceType'),
          dict: backendDict(DictEnum.ResourceTypeEnum),
          form: {
            helper: {
              position: 'label',
              text: '菜单:左侧显示的菜单或隐藏的菜单 \n数据：数据权限',
            },
          },
          type: 'dict-radio',
        },
        parentName: {
          title: '上级节点',
          type: 'text',
          form: {
            component: { disabled: true },
            value: '根节点',
          },
        },
        code: {
          title: $t('devOperation.application.defResource.code'),
          type: 'text',
          form: {
            helper: {
              position: 'label',
              text: '编码规则：按层级结构编码，使用:作为分隔符 \n建议以view、add、edit、delete、export、import、download、upload等关键词结尾',
            },
          },
        },
        name: {
          title: $t('devOperation.application.defResource.name'),
          type: 'text',
        },
        icon: {
          title: $t('devOperation.application.defResource.icon'),
          type: 'text',
          form: {
            render: (scope: ScopeContext) => {
              return <IconPicker v-model:value={scope.form.icon} />;
              // return (
              //   <>
              //     <Input
              //       allow-clear
              //       placeholder="点击这里选择图标"
              //       v-model:value={scope.form.icon}
              //     >
              //       {{
              //         addonAfter: () => (
              //           <IconPicker
              //             model-value-prop="value"
              //             type="icon"
              //             v-model={scope.form.icon}
              //           />
              //         ),
              //       }}
              //     </Input>
              //   </>
              // );
            },
          },
        },
        sortValue: {
          title: $t('devOperation.application.defResource.sortValue'),
          type: 'number',
        },
        state: {
          title: $t('devOperation.application.defResource.state'),
          dict: STATE_CONSTANT_DICT,
          addForm: { value: true },
          type: 'dict-radio',
        },
        isGeneral: {
          title: $t('devOperation.application.defResource.isGeneral'),
          dict: YES_NO_CONSTANT_DICT,
          type: 'dict-radio',
        },

        openWith: {
          title: $t('devOperation.application.defResource.openWith'),
          dict: backendDict(DictEnum.ResourceOpenWithEnum),
          type: 'dict-radio',
          form: {
            helper: {
              position: 'label',
              text: '组件：在框架内打开组件页面 \n内链：在框架内打开网页地址 \n外链：新开窗口打开网页地址',
            },
            show: compute((context: ComputeContext) => {
              return [ResourceTypeEnum.MENU].includes(
                context.form.resourceType,
              );
            }),
            valueChange({ form, value }) {
              switch (value) {
                case ResourceOpenWithEnum.INNER_CHAIN: {
                  form.component = 'IFRAME';
                  break;
                }
                case ResourceOpenWithEnum.OUTER_CHAIN: {
                  form.component = 'IFRAME';
                  break;
                }
                default: {
                  break;
                }
              }
            },
          },
        },
        isHidden: {
          title: $t('devOperation.application.defResource.isHidden'),
          dict: YES_NO_CONSTANT_DICT,
          form: {
            show: compute((context: ComputeContext) => {
              return [ResourceTypeEnum.MENU].includes(
                context.form.resourceType,
              );
            }),
          },
          type: 'dict-radio',
        },
        link: {
          title: $t('devOperation.application.defResource.link'),
          form: {
            col: { span: 24 },
            show: compute((context: ComputeContext) => {
              return (
                [ResourceTypeEnum.MENU].includes(context.form.resourceType) &&
                [
                  ResourceOpenWithEnum.INNER_CHAIN,
                  ResourceOpenWithEnum.OUTER_CHAIN,
                ].includes(context.form.openWith)
              );
            }),
          },
          type: 'text',
        },
        path: {
          title: $t('devOperation.application.defResource.path'),
          form: {
            show: compute((context: ComputeContext) => {
              return [ResourceTypeEnum.MENU].includes(
                context.form.resourceType,
              );
            }),
          },
          type: 'text',
        },
        component: {
          title: $t('devOperation.application.defResource.component'),
          form: {
            show: compute((context: ComputeContext) => {
              return [ResourceTypeEnum.MENU].includes(
                context.form.resourceType,
              );
            }),
            component: {
              disabled: compute((context: ComputeContext) => {
                return [
                  ResourceOpenWithEnum.INNER_CHAIN,
                  ResourceOpenWithEnum.OUTER_CHAIN,
                ].includes(context.form.openWith);
              }),
            },
          },
          type: 'text',
        },
        redirect: {
          title: $t('devOperation.application.defResource.redirect'),
          form: {
            show: compute((context: ComputeContext) => {
              return [ResourceTypeEnum.MENU].includes(
                context.form.resourceType,
              );
            }),
          },
          type: 'text',
        },
        subGroup: {
          title: $t('devOperation.application.defResource.subGroup'),
          form: {
            show: compute((context: ComputeContext) => {
              return [ResourceTypeEnum.MENU].includes(
                context.form.resourceType,
              );
            }),
          },
          type: 'text',
        },
        dataScope: {
          title: $t('devOperation.application.defResource.dataScope'),
          form: {
            show: compute((context: ComputeContext) => {
              return [ResourceTypeEnum.DATA].includes(
                context.form.resourceType,
              );
            }),
            col: { span: 24 },
          },
          type: 'dict-radio',
          dict: backendDict(DictEnum.DataScopeEnum),
        },
        isDef: {
          title: $t('devOperation.application.defResource.isDef'),
          dict: YES_NO_CONSTANT_DICT,
          form: {
            show: compute((context: ComputeContext) => {
              return [ResourceTypeEnum.DATA].includes(
                context.form.resourceType,
              );
            }),
            col: {
              span: compute((context: ComputeContext) => {
                return context.form.dataScope === DataScopeEnum.CUSTOM
                  ? 12
                  : 24;
              }),
            },
          },
          type: 'dict-radio',
        },
        customClass: {
          title: $t('devOperation.application.defResource.customClass'),
          form: {
            show: compute((context: ComputeContext) => {
              return (
                [ResourceTypeEnum.DATA].includes(context.form.resourceType) &&
                context.form.dataScope === DataScopeEnum.CUSTOM
              );
            }),
            component: { placeholder: '以"DATA_SCOPE_"为前缀的自定义实现类' },
          },
          type: 'text',
        },

        fieldIsSecret: {
          title: $t('devOperation.application.defResource.fieldIsSecret'),
          dict: YES_NO_CONSTANT_DICT,
          form: {
            show: compute((context: ComputeContext) => {
              return [ResourceTypeEnum.FIELD].includes(
                context.form.resourceType,
              );
            }),
          },
          type: 'dict-radio',
        },
        fieldIsEdit: {
          title: $t('devOperation.application.defResource.fieldIsEdit'),
          dict: YES_NO_CONSTANT_DICT,
          form: {
            show: compute((context: ComputeContext) => {
              return [ResourceTypeEnum.FIELD].includes(
                context.form.resourceType,
              );
            }),
          },
          type: 'dict-radio',
        },
        resourceApiList: {
          title: '接口',
          viewForm: { ignoreUseCellComponent: true },
          form: {
            col: { span: 24 },
            show: compute((context: ComputeContext) => {
              return [ResourceTypeEnum.BUTTON, ResourceTypeEnum.MENU].includes(
                context.form.resourceType,
              );
            }),
            component: {
              name: Api,
              vModel: 'modelValue',
              props: { mode: props.context.type },
            },
          },
          type: 'text',
        },
        metaJson: {
          title: $t('devOperation.application.defResource.metaJson'),
          viewForm: { ignoreUseCellComponent: true },
          form: {
            col: { span: 24 },
            component: {
              name: Meta,
              vModel: 'modelValue',
              props: { mode: props.context.type },
            },
          },
          type: 'text',
        },
        describe: {
          title: $t('devOperation.application.defResource.describe'),
          addForm: {},
          form: {
            col: { span: 24 },
            component: { autoSize: { minRows: 2, maxRows: 3 } },
          },
          type: 'textarea',
        },
      },
    },
  };
}

const CODE_REG = /^[\w:,;*]*$/;

export const frontRules = (formRef: Ref): FormRulesExt => {
  return {
    code: {
      type: RuleType.and,
      rules: [
        {
          trigger: ['blur', 'change'],
          type: 'string',
          asyncValidator: async (_, value, callback) => {
            if (value) {
              const { getFormData } = formRef.value;
              const model = await getFormData();
              if (!CODE_REG.test(value)) {
                return callback(
                  '编码只能包括: [英文大小写][数字][_][;][,][:][*]',
                );
              }
              if (await DefResourceApi.check(value, model.id)) {
                return callback('编码已经存在');
              }
            }
            return callback();
          },
        },
      ],
    },
    resourceType: {
      type: RuleType.and,
      rules: [
        {
          trigger: ['blur', 'change'],
          type: 'string',
          asyncValidator: async (_: any, value: string, callback) => {
            if (value) {
              const { getFormData } = formRef.value;
              const model = await getFormData();

              if (model?.parentId === '0' || !model?.parentId) {
                if (value === ResourceTypeEnum.DATA) {
                  return callback('数据权限必须挂载在菜单下');
                }
              } else if (value === ResourceTypeEnum.MENU) {
                if (ResourceTypeEnum.MENU !== model?.parentResourceType) {
                  return callback('菜单只能挂载在菜单下级');
                }
                if (model?.parentIsHidden) {
                  return callback('菜单不能挂载在隐藏菜单下级');
                }
              }

              if (model?.parentResourceType === ResourceTypeEnum.BUTTON) {
                if (value === ResourceTypeEnum.MENU) {
                  return callback('按钮下不能添加菜单');
                } else if (value === ResourceTypeEnum.DATA) {
                  return callback('按钮下不能添加数据');
                }
              } else if (model?.parentResourceType === ResourceTypeEnum.FIELD) {
                return callback('字段下不能添加子资源');
              }
            }
            return callback();
          },
        },
      ],
    },
    name: {
      type: RuleType.and,
      rules: [
        {
          trigger: ['blur', 'change'],
          type: 'string',
          asyncValidator: async (_: any, value: string, callback) => {
            if (value) {
              const { getFormData } = formRef.value;
              const model = getFormData();
              if (
                [ResourceTypeEnum.MENU].includes(model.resourceType) &&
                (await DefResourceApi.checkName(
                  value,
                  model.applicationId,
                  model?.id,
                ))
              ) {
                return callback(
                  `${$t('devOperation.application.defResource.name')}已经存在`,
                );
              }
            }
            return callback();
          },
        },
      ],
    },
    link: {
      type: RuleType.and,
      rules: [
        {
          trigger: ['blur', 'change'],
          type: 'string',
          required: true,
          asyncValidator: async (_: any, value: string, callback) => {
            if (value) {
              if (isUrl(value)) {
                return callback();
              }
              return callback(`请填写有效的url`);
            } else {
              return callback(
                `请输入${$t('devOperation.application.defResource.link')}`,
              );
            }
          },
        },
      ],
    },
    path: {
      type: RuleType.and,
      rules: [
        {
          trigger: ['blur', 'change'],
          type: 'string',
          required: true,
          asyncValidator: async (_: any, value: string, callback) => {
            if (value) {
              const { getFormData } = formRef.value;
              const model = getFormData();

              if (model?.parentId === '0' && !value.startsWith('/')) {
                return callback(
                  `1级资源的${$t('devOperation.application.defResource.path')}必须以/开头`,
                );
              }
              if (
                await DefResourceApi.checkPath(
                  value,
                  model.applicationId,
                  model?.id,
                )
              ) {
                return callback(
                  `${$t('devOperation.application.defResource.path')}已经存在`,
                );
              }

              return callback();
            } else {
              return callback(
                `请输入${$t('devOperation.application.defResource.path')}`,
              );
            }
          },
        },
      ],
    },
    component: {
      type: RuleType.and,
      rules: [
        {
          trigger: ['blur', 'change'],
          type: 'string',
          required: true,
          asyncValidator: async (_: any, value: string, callback) => {
            if (!value) {
              return callback(
                `请输入${$t('devOperation.application.defResource.component')}`,
              );
            }
          },
        },
      ],
    },
    customClass: {
      type: RuleType.and,
      rules: [
        {
          trigger: ['blur', 'change'],
          type: 'string',
          required: true,
          asyncValidator: async (_: any, value: string, callback) => {
            const { getFormData } = formRef.value;
            const model = getFormData();

            if (model.dataScope === DataScopeEnum.CUSTOM && !value) {
              return callback('不能为空');
            }
            return callback();
          },
        },
      ],
    },
  };
};
